home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1997 May / PC Plus Super CD Issue 127 (May 1997).iso / handson / delphi / dbread / tlunit1.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1997-02-04  |  12.9 KB  |  385 lines

  1. unit Tlunit1;
  2. (* PC PLUS Sample Delphi program to illustrate the use of TList objects. *)
  3. (* Also shows how to import data from a text file:                       *)
  4. (*    procedure TForm1.ImportBtnClick(Sender: TObject);                  *)
  5. (* at the end of this unit.                                              *)
  6.  
  7. (* DELPHI 2 PROGRAMMERS NOTE! When reading strings from text files, you  *)
  8. (* must specify a maximum string size. Delphi 2's default string is      *)
  9. (* dynamically allocated. Delphi 1's default string is 255 chars.        *)
  10. (* You can either declare a fixed-size Delphi 2 string (e.g. string[255])*)
  11. (* or you can 'turn off' Delphi 2's long strings using the {$H-} compiler*)
  12. (* directive. For simplicity, this is the approach taken in this project *)
  13.  
  14. {$IFDEF VER90}
  15. {$H-}   (* turn off long strings if this is Delphi 2*)
  16. {$ENDIF}
  17. interface
  18.  
  19. uses
  20.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  21.   Forms, Dialogs, StdCtrls, ExtCtrls,
  22.   StrUtils;
  23.  
  24. type
  25.  
  26. { Define the objects to be put into the TList }
  27. Thing = class(TObject)
  28.   name        : string[20];
  29.   description : string [50];
  30.   value       : integer;
  31. end;
  32.  
  33.  
  34.   TForm1 = class(TForm)
  35.     TListCreateBtn: TButton;
  36.     MessageBox: TMemo;
  37.     FreeThingsBtn: TButton;
  38.     TListDestroyBtn: TButton;
  39.     CountThingsBtn: TButton;
  40.     ShowThingsBtn: TButton;
  41.     ShowFirstBtn: TButton;
  42.     ShowLastBtn: TButton;
  43.     ExchangeFirstandLastBtn: TButton;
  44.     ExitBtn: TButton;
  45.     AddTenThingsBtn: TButton;
  46.     Panel1: TPanel;
  47.     Label1: TLabel;
  48.     Label2: TLabel;
  49.     Label3: TLabel;
  50.     NameEd: TEdit;
  51.     DescEd: TEdit;
  52.     ValEd: TEdit;
  53.     AddThingBtn: TButton;
  54.     ClearMessagesBtn: TButton;
  55.     ImportBtn: TButton;
  56.     procedure TListCreateBtnClick(Sender: TObject);
  57.     procedure AddThingBtnClick(Sender: TObject);
  58.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  59.     procedure FreeThingsBtnClick(Sender: TObject);
  60.     procedure TListDestroyBtnClick(Sender: TObject);
  61.     procedure CountThingsBtnClick(Sender: TObject);
  62.     procedure ShowThingsBtnClick(Sender: TObject);
  63.     procedure ExitBtnClick(Sender: TObject);
  64.     procedure ShowFirstBtnClick(Sender: TObject);
  65.     procedure ShowLastBtnClick(Sender: TObject);
  66.     procedure ExchangeFirstandLastBtnClick(Sender: TObject);
  67.     procedure FormActivate(Sender: TObject);
  68.     procedure AddTenThingsBtnClick(Sender: TObject);
  69.     procedure ClearMessagesBtnClick(Sender: TObject);
  70.     procedure ImportBtnClick(Sender: TObject);
  71.   private
  72.     { Private declarations }
  73.   public
  74.     { Public declarations }
  75.     procedure FreeThings;
  76.     procedure FreeThingList;
  77.     function  ThingListExists : boolean;
  78.     function  ThingsInTheList : boolean;
  79.     procedure ShowThing( T : Thing );
  80. end;
  81.  
  82.  
  83.  
  84. var
  85.   Form1: TForm1;
  86.   MyThingList : TList;     { declare a TList variable }
  87.  
  88. implementation
  89.  
  90. {$R *.DFM}
  91.  
  92. function TForm1.ThingListExists : boolean;
  93. { Return true if the TList has been created and points to something }
  94. begin
  95.    if MyThingList = nil then
  96.       ThingListExists := false
  97.    else
  98.       ThingListExists := true;
  99. end;
  100.  
  101. function  TForm1.ThingsInTheList : boolean;
  102. { Return true if TList has been created and has some objects. Otherwise }
  103. { print an explanatory message.                                         }
  104. begin
  105.   ThingsInTheList := false;
  106.   if not ThingListExists then
  107.      MessageBox.Lines.Add( 'Thing List doesn''t exist!' )
  108.   else if MyThingList.Count = 0 then
  109.      MessageBox.Lines.Add( 'There are no Things in the list!' )
  110.   else ThingsInTheList := True;
  111. end;
  112.  
  113. procedure TForm1.FreeThings;
  114. var
  115.    i : integer;
  116. begin
  117.   { go through the TList, freeing the items }
  118.   if ThingListExists then
  119.   begin
  120.      For i := 0 to MyThingList.Count - 1 do
  121.          if MyThingList.Items[i] <> nil then
  122.             Thing(MyThingList.Items[i]).Free;
  123.      MyThingList.Clear;
  124.   end;
  125. end;
  126.  
  127. procedure TForm1.FreeThingList;
  128.   { free the TList }
  129. begin
  130.   If ThingListExists then
  131.   begin
  132.      FreeThings;          { make sure all the objects are freed }
  133.      MyThingList.Free;    { then free the TList itself          }
  134.      MyThingList := nil;  { Finally, re-set TList to nil        }
  135.   end;
  136. end;
  137.  
  138.  
  139. procedure TForm1.TListCreateBtnClick(Sender: TObject);
  140. begin
  141.   if not ThingListExists then
  142.   begin
  143.     MyThingList := TList.Create; { Create the TList }
  144.     MessageBox.Lines.Add( 'MyThingList has now been created.');
  145.   end
  146.   else
  147.     MessageBox.Lines.Add( 'ERROR: MyThingList has already been created!');
  148. end;
  149.  
  150. procedure TForm1.AddThingBtnClick(Sender: TObject);
  151. var
  152.    i           :integer;
  153.    FieldsOK    : boolean;
  154.    newthing    : Thing;
  155. begin
  156. { --- this whole first section checks that all the data fields contain --- }
  157. { --- appropriate values to create and add an object to our TList      --- }
  158.  
  159.  FieldsOK := true; { start by assuming that field contents are valid       }
  160.  if ( (NameEd.Text = '') or (DescEd.Text = '') or (ValEd.Text = '') )then
  161.  begin
  162.       MessageDlg(  'You must enter a Name, a Description and a Value.',
  163.                    mtInformation, [mbOk], 0);
  164.       FieldsOK := false; { if they aren't valid, make this variable false }
  165.  end
  166.  else
  167.  begin
  168.     try   { check that ValEd.Text can be converted to an integer }
  169.       i := StrToInt(ValEd.Text);
  170.     except
  171.       on EConvertError do
  172.       begin
  173.          i := 0;
  174.          FieldsOK := false;
  175.          MessageDlg(  '"' + ValEd.Text + '" is not a valid integer!',
  176.                       mtInformation, [mbOk], 0);
  177.       end;
  178.     end; { try...except...}
  179.  end;
  180.  if FieldsOK then
  181.  if not ThingListExists then { check that the TList has been created }
  182.     MessageDlg( 'ERROR: Create a TList before you add an object!',
  183.                       mtInformation, [mbOk], 0)
  184.  else
  185.  { If all is well, create a Thing object and add it to the ThingList TList }
  186.  begin
  187.     newthing := Thing.Create;
  188.     newthing.name := NameEd.Text;
  189.     newthing.description := DescEd.Text;
  190.     newthing.value := i;       { our integer version of ValEd.Text }
  191.     MyThingList.Add(newthing); { add it to the TList               }
  192.     MessageBox.Lines.Add( 'New thing added at position '
  193.                     + IntToStr(MyThingList.Count) );
  194.  end;
  195. end;
  196.  
  197. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  198. begin
  199.    { clean up when the application terminates }
  200.    FreeThings;
  201.    FreeThingList;
  202. end;
  203.  
  204. procedure TForm1.FreeThingsBtnClick(Sender: TObject);
  205. begin
  206.    if ThingsInTheList then
  207.    begin
  208.       FreeThings;
  209.       MessageBox.Lines.Add( 'All Things have been destroyed.');
  210.    end;
  211. end;
  212.  
  213. procedure TForm1.TListDestroyBtnClick(Sender: TObject);
  214. { Destroy the ThingList }
  215. begin
  216.   if not ThingListExists then { if it isn't created, it can't be destroyed }
  217.     MessageBox.Lines.Add( 'MyThingList is already free.')
  218.   else                        { if it contains things, free them first     }
  219.   if MyThingList.Count > 0 then
  220.          MessageBox.Lines.Add( 'Please free MyThingList''s objects first.')
  221.   else
  222.   begin
  223.     FreeThingList;
  224.     MessageBox.Lines.Add( 'OK. MyThingList has now been freed.');
  225.   end;
  226. end;
  227.  
  228. procedure TForm1.CountThingsBtnClick(Sender: TObject);
  229. begin
  230.   if ThingsInTheList then
  231.      MessageBox.Lines.Add(IntToStr( MyThingList.Count )
  232.                                     + ' items in the TList. ' );
  233. end;
  234.  
  235. procedure TForm1.ShowThing( t : Thing );
  236. { Given a Thing 't', print its data fields in the MessageBox memo }
  237. var
  238.    s : string;
  239. begin
  240.    s := 'Thing[' + IntToStr(MyThingList.IndexOf(t)) +
  241.        '] Name: "' + t.name
  242.        + '", Description: "' + t.description
  243.        + '", Value: ' + IntToStr(t.Value);
  244.    MessageBox.Lines.Add( s );
  245. end;
  246.  
  247.  
  248. procedure TForm1.ShowThingsBtnClick(Sender: TObject);
  249. { display data of all Things in memo }
  250. var
  251.    i : integer;
  252. begin
  253.   if ThingsInTheList then
  254.     for i := 0 to MyThingList.Count - 1 do
  255.       ShowThing( MyThingList.Items[i] );
  256. end;
  257.  
  258. procedure TForm1.ExitBtnClick(Sender: TObject);
  259. begin
  260.    Close;
  261. end;
  262.  
  263.  
  264. procedure TForm1.ShowFirstBtnClick(Sender: TObject);
  265. { display data of first Thing in memo }
  266. begin
  267.    If ThingsInTheList then
  268.       ShowThing(MyThingList.First);
  269. end;
  270.  
  271. procedure TForm1.ShowLastBtnClick(Sender: TObject);
  272. { display data of last Thing in memo }
  273. begin
  274.    If ThingsInTheList then
  275.       ShowThing(MyThingList.Last);
  276. end;
  277.  
  278. procedure TForm1.ExchangeFirstandLastBtnClick(Sender: TObject);
  279. { swap first and last things in the TList }
  280. begin
  281.    if ThingsInTheList then
  282.    if MyThingList.Count = 1 then
  283.       MessageBox.Lines.Add('ERROR: You need at least 2 items to exchange them!')
  284.    else
  285.    begin
  286.       MyThingList.Exchange(
  287.          MyThingList.IndexOf(MyThingList.First),  { use IndexOf to provide an  }
  288.          MyThingList.IndexOf(MyThingList.Last) ); { integer value of First+Last}
  289.       MessageBox.Lines.Add('First and Last items have been exchanged.');
  290.    end;
  291. end;
  292.  
  293. procedure TForm1.FormActivate(Sender: TObject);
  294. begin
  295.    { In fact, a TList is automatically initialised to nil }
  296.    { prior to being created. Still, best to be explicit   }
  297.    { about this!                                          }
  298.    MyThingList := nil;
  299. end;
  300.  
  301. procedure TForm1.AddTenThingsBtnClick(Sender: TObject);
  302. var
  303.    i : integer;
  304.    newthing : Thing;
  305. begin
  306.  if not ThingListExists then { check that the TList has been created }
  307.     MessageDlg( 'ERROR: Create a TList before you add objects!',
  308.                       mtInformation, [mbOk], 0)
  309.     else
  310.     begin
  311.        for i := 1 to 10 do
  312.        begin
  313.            newthing := Thing.Create;
  314.            newthing.name := 'A Thing';
  315.            newthing.description := 'A Description';
  316.            newthing.value := i;
  317.            MyThingList.Add(newthing); { add it to the TList }
  318.        end;
  319.        MessageBox.Lines.Add( 'Ten things added to the list.' );
  320.     end;
  321. end;
  322.  
  323. procedure TForm1.ClearMessagesBtnClick(Sender: TObject);
  324. begin
  325.    MessageBox.Clear;
  326. end;
  327.  
  328. { ---------------------------------------------------------------------------- }
  329. { ------------------ THE NEW CODE STARTS HERE -------------------------------- }
  330. { ---------------------------------------------------------------------------- }
  331. { This procedure imports comma-delimited data from the file Test.txt           }
  332. { Note that, in real-world application, you would need to add a good deal of   }
  333. { error checking to operations such as this. For example, you would need to    }
  334. { check that the directory is valid (e.g. recover when if you are trying       }
  335. { to read from an empty floppy disk drive). And you'd need to check that each  }
  336. { item is valid. For simplicity, I have omitted these checks. As a result, the }
  337. { following assumptions are made:                                              }
  338. { 1) That the file, Test.txt contains a list of records, 1 record per line     }
  339. { 2) That each line comprises a comma-delimited list of 3 items                }
  340. { 3) That items 1 and 2 are Strings and that item 3 can be converted to integer}
  341. procedure TForm1.ImportBtnClick(Sender: TObject);
  342. var
  343.    TFile         : TextFile;  
  344.    TLine         : string;
  345.    str, f, r     : string;
  346.    newthing      : Thing;
  347. begin
  348.     if not FileExists( 'Test.txt' ) then        { Check that input file exists }
  349.         ShowMessage('File: TEST.TXT not found!')
  350.     else
  351.     begin
  352.       if not ThingListExists then
  353.         MyThingList := TList.Create;            { Create the TList             }
  354.            { If the file exists, then Open it for reading                      }
  355.       AssignFile(TFile, 'Test.txt' );
  356.       Reset(TFile);
  357.       MessageBox.Lines.Add( '* File Test.txt has been opened for reading. *' );
  358.            { Read lines until at Eof (End of file)                             }
  359.       While not Eof(TFile) do
  360.       begin
  361.         newthing := Thing.Create;  { create an object of type Thing            }
  362.         Readln(TFile, TLine );     { read a line from the input file           }
  363.         MessageBox.Lines.Add( 'Line read: [' + TLine + ']' );
  364.                                    { parse the line into data items to match   }
  365.         firstrestStr(TLine, f, r );{ the data fields of a Thing object         }
  366.         newthing.name := f;
  367.         str := r;
  368.         firstrestStr(str, f, r );
  369.         newthing.description := f;
  370.         str := r;
  371.         firstrestStr(str, f, r );
  372.         newthing.value := StrToInt( f );
  373.                                   { Add newthing object to MyThingList TList   }
  374.         MyThingList.Add( newthing );
  375.       end; { END: While not Eof Loop }
  376.       CloseFile(TFile);           { When there's no more to read, close file   }
  377.       MessageBox.Lines.Add( '* File Test.txt has now been closed! *' );
  378.     end; { END: FileExists Block }
  379. end;
  380. { ---------------------------------------------------------------------------- }
  381. { ------------------ THE NEW CODE ENDS HERE ---------------------------------- }
  382. { ---------------------------------------------------------------------------- }
  383.  
  384. end.
  385.